/* GNU Mailutils -- a suite of utilities for electronic mail
   Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA */

#ifndef	SMALLBRAIN_SILHOUETTE_H
#define SMALLBRAIN_SILHOUETTE_H
#include <iostream>
#include <set>
#include "constants.h"

/**
*
* \file silhouette.h
* \brief La machine et données abstraites exploitées par ma solution
* \date 20 Avril 2011
* \author Ice and Magic
*
* \mainpage
* Je n'ai aucun mérite pour le travail théorique exploité par cette implémentation. Tous les droits reviennent
* à celui ou à ceux qui l'ont développé. Ma méthode de résolution repose sur l'intuition donnée dans ces blogs:
* ref1: http://chantal.andrieubarrault.perso.sfr.fr/mathfon/agreable.php
* ref2: http://jean-paul.davalan.pagesperso-orange.fr/arit/narcisse/
* ref3: http://jean-paul.davalan.pagesperso-orange.fr/arit/narcisse/demo.txt
*
* L'idée repose sur le calcul d'une classe d'équivalence qui représente tous les paramètres d'une fonction Armstrong.
* Deux remarques sont à noter
*      1. L'ordre des chiffres d'un paramètre n'a aucun impact sur la valeur de son image.
*      2. Les zéros dans un paramètre ne sont pas significatifs pour son image.
*  Parcourir tout un ensemble d'entier donne le même résultat que traiter la classe d'équivalence de cet ensemble.
*
* Définition: Une silhouette S d'un entier N est composée des nombres d'occurrences de ses chiffres.
* Exemples: N=120, S=21
*           S=00992, N possibles: 992,929,299, 9920, 9902, 9092, 90902, ...
*
* Il est trivial que l'image d'un entier est égale à celle de sa silhouette.
*
* Le travail théorique [\cite ref1]  nous donne plusieurs corollaires:
*      1. Autocomposition de la relation d'Armstrong, appliquée à un paramètre X, converge vers:
*              =) Un point fixe,  dans ce cas X est appelé "attracteur" ou "agréable".
*              =) Un cycle.
*      2. Par définition, un point fixe est un "attracteur".
*      3. Les silhouettes de tous les points fixes sont dans la classe d'equivalence.
*
* Ce fichier contient deux "solutions" importantes :
*      * La classe "Silhouette" représente un élément de la classe d'équivalence de l'ensemble des entiers pour la
* relation Armstrong.
*      * La fonction "generateur_silhouettes" qui traverse tous les élément de cette classe d'équivalence.
*/



/**
 * \brief représente une silhouette d'un entier
 * coucou
 */

class Silhouette{
public:
//! \brief occurrences de chiffres
//! \remark short est le type le plus petit supporté par l'auto-vectoriseur d'icc

short	digit_occurrences[__DIGITS];	


public:

//! \brief Initialisation de la silhouette par un nombre.
Silhouette(__type=0);		
//! \brief Tout est alloué statiquement, le destructeur ne fait rien.
~Silhouette();

//! \brief retourne le nombre d'occurrences du chiffre "i"
inline short&		operator[](int i);
			
			//! \brief comparaison entre deux silhouettes, le zéro est non significatif
inline bool			operator==(Silhouette&) ;


//! \brief calcule l'image de la silhouette par la fonction d'Armstrong d'ordre k
//! Très consommatrice en temps de calcul
__type			compute_F_x(int k) ;
			
			//! \brief calcule l'image de la silhouette par la fonction d'Armstrong d'ordre k
			//! \param p un vecteur contenant les puissances adéquates pour chaque chiffre.
__type			compute_F_x(const __type* p);

 			//! \brief suis-je une silhouette d'un point fixe?
			//! \see init_powers print_powers power_matrix is_digital_invariant
 bool			is_digital_invariant(const __type*);
			//! \brief Collecter tous les points fixe qui peuvent être générés par cette silhouette.
			//! \param k appliquer Armstrong des ordres autour k
			//! \param powers une matrice contenant C^k ... C: un chiffre, k: nb chiffres supportés
			//! \see init_powers print_powers power_matrix is_digital_invariant

std::set<__type>	collect_invariants(int );
std::set<__type>	collect_invariants(int k,const __type** powers) ;
			//! \brief un affichage humain-friendly. Résultat dans une string.
std::string		humain_friendly_print() ;
			//! \brief retourne le nombre de chiffre.
int			nb_digits() ;

/*			//! \ brief surcharge de l'opérateur d'affectation.
			//! Rajouté par souci d'optimisation.
inline Silhouette&	operator=(Silhouette&);*/
};


			//! \brief Créer un flux à partir d'une silhouette, puis le diriger vers un flux de sortie.

std::ostream&		operator<<(std::ostream&,  Silhouette&);

			/**
			 * \brief fonction génératrice des silhouettes de la classe d'équivalence de entiers définie par la relation d'Armstrong
			 */
std::set<__type>	generateur_silhouettes(
		#ifdef FULL_VERBOSE
		__type ,
		#endif
		Silhouette , int ,int, int);
#endif
